home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / stdwin.zoo / alfa / draw.c < prev    next >
C/C++ Source or Header  |  1989-10-18  |  8KB  |  471 lines

  1. /* ALFA STDWIN -- DRAWING. */
  2.  
  3. #include "alfa.h"
  4.  
  5. /* Cause a redraw of part of a window. */
  6.  
  7. /*ARGSUSED*/
  8. void
  9. wchange(win, left, top, right, bottom)
  10.     WINDOW *win;
  11.     int left, top;
  12.     int right, bottom;
  13. {
  14.     int id= win - winlist;
  15.     int i;
  16.     
  17.     if (id < 0 || id >= MAXWINDOWS || !win->open)
  18.         return;
  19.     top -= win->offset;
  20.     bottom -= win->offset;
  21.     if (top < win->top)
  22.         top= win->top;
  23.     if (bottom > win->bottom)
  24.         bottom= win->bottom;
  25.     for (i= top; i < bottom; ++i)
  26.         uptodate[i]= FALSE;
  27.     _wnewtitle(win);
  28. }
  29.  
  30. /* (Try to) make sure a particular part of a window is visible,
  31.    by scrolling in distant parts if necessary. */
  32.  
  33. static void scrollupdate();
  34.  
  35. /*ARGSUSED*/
  36. void
  37. wshow(win, left, top, right, bottom)
  38.     WINDOW *win;
  39.     int left, top;
  40.     int right, bottom;
  41. {
  42.     int id= win - winlist;
  43.     int offset;
  44.     int extra;
  45.     int dv;
  46.     
  47.     if (id < 0 || id >= MAXWINDOWS || !win->open)
  48.         return;
  49.     extra= ( (win->bottom - win->top) - (bottom - top) ) / 2;
  50.     if (extra < 0)
  51.         extra= 0;
  52.     offset= win->offset;
  53.     if (bottom > win->bottom + offset)
  54.         offset= bottom - win->bottom + extra;
  55.     if (top < win->top + offset)
  56.         offset= top - win->top - extra;
  57.     if (win->top + offset < 0)
  58.         offset= -win->top;
  59.     dv= offset - win->offset;
  60.     if (dv == 0)
  61.         return;
  62.     win->offset= offset;
  63.     /* Now we'll use top, bottom to indicate the changed part. */
  64.     top= win->top;
  65.     bottom= win->bottom;
  66.     scrollupdate(top, bottom, dv);
  67.     trmscrollup(top, bottom-1, dv);
  68. }
  69.  
  70. /* Similar, but by giving an explicit new origin */
  71.  
  72. /*ARGSUSED*/
  73. void
  74. wsetorigin(win, h, v)
  75.     WINDOW *win;
  76.     int h, v;
  77. {
  78.     int id= win - winlist;
  79.     int top, bottom;
  80.     int dv;
  81.  
  82.     if (id < 0 || id >= MAXWINDOWS || !win->open)
  83.         return;
  84.     dv = (v - win->top) - win->offset;
  85.     if (dv == 0)
  86.         return;
  87.     win->offset += dv;
  88.     top = win->top;
  89.     bottom = win->bottom;
  90.     scrollupdate(top, bottom, dv);
  91.     trmscrollup(top, bottom-1, dv);
  92. }
  93.  
  94. /* Scroll the update bits */
  95.  
  96. static void
  97. scrollupdate(top, bottom, dv)
  98.     int top, bottom;
  99.     int dv;
  100. {
  101.     int i;
  102.     for (i= top; i < bottom; ++i) {
  103. #ifdef BUGGY
  104.         /* This code no longer works --
  105.            should copy the actual contents as well. */
  106.         if (i+dv >= top && i+dv < bottom && uptodate[i+dv])
  107.             uptodate[i]= TRUE;
  108.         else
  109. #endif
  110.             uptodate[i]= FALSE;
  111.     }
  112. }
  113.  
  114. /* Set the caret (cursor) position. */
  115.  
  116. void
  117. wsetcaret(win, h, v)
  118.     WINDOW *win;
  119.     int h, v;
  120. {
  121.     win->curh= h;
  122.     win->curv= v;
  123.     wshow(win, h, v, h+1, v+1);
  124. }
  125.  
  126. /* Remove the caret altogether. */
  127.  
  128. void
  129. wnocaret(win)
  130.     WINDOW *win;
  131. {
  132.     win->curh= win->curv= -1;
  133. }
  134.  
  135. /* Cause a redraw of the window 's title bar. */
  136.  
  137. void
  138. _wnewtitle(win)
  139.     WINDOW *win;
  140. {
  141.     if (win->top > 0)
  142.         uptodate[win->top-1]= FALSE;
  143. }
  144.  
  145. static char *textline[MAXLINES];
  146. static short textlen[MAXLINES];
  147. static char texttouched[MAXLINES];
  148.  
  149. static TEXTATTR draw_saveattr;
  150. static WINDOW *draw_win;
  151.  
  152. /* Compute the smallest rectangle that needs an update.
  153.    As a side effect, uptodate is set to TRUE for the affected lines,
  154.    and the lines are cleared and set to touched
  155.    (but no actual output is performed).
  156.    Return FALSE if the rectangle is empty. */
  157.  
  158. bool
  159. wgetchange(win, pleft, ptop, pright, pbottom)
  160.     WINDOW *win;
  161.     int *pleft, *ptop, *pright, *pbottom;
  162. {
  163.     int top= win->bottom;
  164.     int bottom= win->top;
  165.     int i;
  166.     
  167.     for (i= win->top; i < win->bottom; ++i) {
  168.         if (!uptodate[i]) {
  169.             texttouched[i]= TRUE;
  170.             textlen[i]= 0;
  171.             uptodate[i]= TRUE;
  172.             if (top > i)
  173.                 top= i;
  174.             bottom= i+1;
  175.         }
  176.     }
  177.     if (top > bottom) {
  178.         *pleft= *pright= *ptop= *pbottom= 0;
  179.         return FALSE;
  180.     }
  181.     else {
  182.         *pleft= 0;
  183.         *pright= columns;
  184.         *ptop= top + win->offset;
  185.         *pbottom= bottom + win->offset;
  186.         return TRUE;
  187.     }
  188. }
  189.  
  190. void
  191. wupdate(win)
  192.     WINDOW *win;
  193. {
  194.     int left, top, right, bottom;
  195.     int i;
  196.     
  197.     wgetchange(win, &left, &top, &right, &bottom);
  198.     
  199.     wbegindrawing(win);
  200.     
  201.     if (win->drawproc != NULL)
  202.         (*win->drawproc)(win, 0, top, columns, bottom);
  203.     
  204.     wenddrawing(win);
  205. }
  206.  
  207. void
  208. wbegindrawing(win)
  209.     WINDOW *win;
  210. {
  211.     int i;
  212.     
  213.     if (draw_win != NULL)
  214.         wenddrawing(draw_win); /* Finish previous job */
  215.     
  216.     for (i= win->top; i < win->bottom; ++i) {
  217.         if (textline[i] == NULL)
  218.             textline[i]= malloc((size_t) (columns+1));
  219.     }
  220.     
  221.     draw_saveattr= wattr;
  222.     wattr= win->attr;
  223.     draw_win= win;
  224. }
  225.  
  226. void
  227. wenddrawing(win)
  228.     WINDOW *win;
  229. {
  230.     int i;
  231.     
  232.     if (draw_win != win) {
  233.         return; /* Bad call */
  234.     }
  235.     
  236.     for (i= win->top; i < win->bottom; ++i) {
  237.         if (texttouched[i]) {
  238.             texttouched[i]= FALSE;
  239.             textline[i][textlen[i]]= EOS;
  240.             trmputdata(i, i, 0, textline[i]);
  241.         }
  242.     }
  243.     
  244.     wattr= draw_saveattr;
  245.     draw_win= NULL;
  246. }
  247.  
  248. void
  249. wdrawtitle(win)
  250.     WINDOW *win;
  251. {
  252.     int titline= win->top - 1;
  253.     char buf[256];
  254.     char *title= win->title == NULL ? "" : win->title;
  255.     int tlen= (int)strlen(title);
  256.     int space= columns-tlen;
  257.     int mask= (win == front) ? 0200 : 0;
  258.     int k;
  259.     
  260.     for (k= 0; k < space/2 - 1; ++k)
  261.         buf[k]= '-'|mask;
  262.     buf[k++]= ' '|mask;
  263.     while (k < columns && *title != EOS)
  264.         buf[k++]= *title++|mask;
  265.     if (k < columns)
  266.         buf[k++]= ' '|mask;
  267.     while (k < columns)
  268.         buf[k++]= '-'|mask;
  269.     buf[k]= EOS;
  270.     trmputdata(titline, titline, 0, buf);
  271.     uptodate[titline]= TRUE;
  272. }
  273.  
  274. int
  275. wdrawtext(h, v, str, len)
  276.     int h, v;
  277.     char *str;
  278.     int len;
  279. {
  280.     int k;
  281.     int mask= (wattr.style == 0) ? 0 : 0200;
  282.     char *text;
  283.     WINDOW *win= draw_win;
  284.     
  285.     if (len < 0)
  286.         len= (int)strlen(str);
  287.     v -= win->offset;
  288.     if (v < win->top || v >= win->bottom || h >= columns || len == 0)
  289.         return h+wtextwidth(str, len);
  290.     text= textline[v];
  291.     k= textlen[v];
  292.     while (k < h)
  293.         text[k++]= ' ';
  294.     while (len > 0) {
  295. #define APPC(c) \
  296.     if (h >= 0) text[h]= (c) | mask; if (++h >= columns) break
  297.         unsigned char c= *str++;
  298.         --len;
  299.         if (c < ' ') {
  300.             APPC('^');
  301.             APPC(c | '@');
  302.         }
  303.         else  if (c < 0177) {
  304.             APPC(c);
  305.         }
  306.         else if (c < 0200) {
  307.             APPC('^');
  308.             APPC('?');
  309.         }
  310.         else {
  311.             APPC('\\');
  312.             APPC('0' | ((c>>3) & 07));
  313.             APPC('0' | ((c>>6) & 07));
  314.             APPC('0' | (c & 07));
  315.         }
  316. #undef APPC
  317.     }
  318.     if (h > textlen[v])
  319.         textlen[v]= h;
  320.     texttouched[v]= TRUE;
  321.     return h+len;
  322. }
  323.  
  324. int
  325. wdrawchar(h, v, c)
  326.     int h, v;
  327.     int c;
  328. {
  329.     char cbuf[2];
  330.     cbuf[0]= c;
  331.     cbuf[1]= EOS;
  332.     return wdrawtext(h, v, cbuf, 1);
  333. }
  334.  
  335. void
  336. wgetwintextattr(win, attr)
  337.     WINDOW *win;
  338.     TEXTATTR *attr;
  339. {
  340.     *attr= win->attr;
  341. }
  342.  
  343. void
  344. wsetwintextattr(win, attr)
  345.     WINDOW *win;
  346.     TEXTATTR *attr;
  347. {
  348.     win->attr= *attr;
  349. }
  350.  
  351. /* Non-text drawing dummy functions: */
  352.  
  353. /*ARGSUSED*/
  354. void
  355. wdrawline(h1, v1, h2, v2)
  356.     int h1, v1, h2, v2;
  357. {
  358. }
  359.  
  360. /*ARGSUSED*/
  361. void
  362. wxorline(h1, v1, h2, v2)
  363.     int h1, v1, h2, v2;
  364. {
  365. }
  366.  
  367. /*ARGSUSED*/
  368. void
  369. wdrawcircle(h, v, radius)
  370.     int h, v;
  371.     int radius;
  372. {
  373. }
  374.  
  375. /*ARGSUSED*/
  376. void
  377. wdrawelarc(h, v, radh, radv, ang1, ang2)
  378.     int h, v;
  379.     int radh, radv;
  380.     int ang1, ang2;
  381. {
  382. }
  383.  
  384. /*ARGSUSED*/
  385. void
  386. wdrawbox(left, top, right, bottom)
  387.     int left, top, right, bottom;
  388. {
  389. }
  390.  
  391. /*ARGSUSED*/
  392. void
  393. wpaint(left, top, right, bottom)
  394.     int left, top, right, bottom;
  395. {
  396. }
  397.  
  398. /*ARGSUSED*/
  399. void
  400. wshade(left, top, right, bottom, percentage)
  401.     int left, top, right, bottom;
  402.     int percentage;
  403. {
  404. }
  405.  
  406. /*ARGSUSED*/
  407. void
  408. winvert(left, top, right, bottom)
  409.     int left, top, right, bottom;
  410. {
  411.     WINDOW *win= draw_win;
  412.     int h, v;
  413.     
  414.     if (left < 0)
  415.         left= 0;
  416.     if (right >= columns)
  417.         right= columns;
  418.     if (left >= right)
  419.         return;
  420.     top -= win->offset;
  421.     bottom -= win->offset;
  422.     if (top < win->top)
  423.         top= win->top;
  424.     if (bottom > win->bottom)
  425.         bottom= win->bottom;
  426.     for (v= top; v < bottom; ++v) {
  427.         int k= textlen[v];
  428.         char *text= textline[v];
  429.         if (k < right) {
  430.             do {
  431.                 text[k++]= ' ';
  432.             } while (k < right);
  433.             textlen[v]= k;
  434.         }
  435.         for (k= left; k < right; ++k)
  436.             text[k] ^= 0200;
  437.         texttouched[v]= TRUE;
  438.     }
  439. }
  440.  
  441. /*ARGSUSED*/
  442. void
  443. werase(left, top, right, bottom)
  444.     int left, top, right, bottom;
  445. {
  446.     WINDOW *win= draw_win;
  447.     int h, v;
  448.     
  449.     if (left < 0)
  450.         left= 0;
  451.     if (right >= columns)
  452.         right= columns;
  453.     if (left >= right)
  454.         return;
  455.     top -= win->offset;
  456.     bottom -= win->offset;
  457.     if (top < win->top)
  458.         top= win->top;
  459.     if (bottom > win->bottom)
  460.         bottom= win->bottom;
  461.     for (v= top; v < bottom; ++v) {
  462.         int k= textlen[v];
  463.         char *text= textline[v];
  464.         if (k > right)
  465.             k= right;
  466.         while (--k >= left)
  467.             text[k]= ' ';
  468.         texttouched[v]= TRUE;
  469.     }
  470. }
  471.